package sw6.pc.network;

import java.io.*;
import java.net.*;

public class Server {
	ServerSocket mServerSocket = null;
	Socket mClientSocket = null;

	DataOutputStream mOutput = null;
	DataInputStream mInput = null;

	boolean mClientConnected = false;

	public boolean isClientConnected() {
		return mClientConnected;
	}

	public boolean startServer(int port) throws IOException{
		// Starts the server on port port
		mServerSocket = new ServerSocket(port);
		
		// The server will accept an incoming connection. If no client is trying to connect, mServerSocket.accept() will hang until a client tries to connect
		mClientSocket = mServerSocket.accept();

		mOutput = new DataOutputStream(mClientSocket.getOutputStream());
		mInput = new DataInputStream(mClientSocket.getInputStream());

		mClientConnected = true;
		return true;
	}
	
	public void broadcastIPAddress(String ip, int port) throws IOException
	{
		InetAddress address = InetAddress.getByName(ip);
		DatagramSocket socket = new DatagramSocket(port);
		socket.setBroadcast(true);
        socket.setReuseAddress(false);
		
        String localIp = getLocalIpAddress();
        
        byte[] stringBytes = localIp.getBytes();
        byte[] buf = new byte[64];
        buf[0] = (byte)stringBytes.length;
        for (int i = 1; i < stringBytes.length+1; i++)
        {
        	buf[i] = stringBytes[i-1];
        }
		
		DatagramPacket p = new DatagramPacket(buf, buf.length, address, port);
		
		socket.send(p);
		
		socket.close();
	}
	
	public String getLocalIpAddress() throws UnknownHostException
	{
		String hostName = InetAddress.getLocalHost().getHostName();
		InetAddress addrs[] = InetAddress.getAllByName(hostName);

		String myIp = "UNKNOWN";
		for (InetAddress addr: addrs) {

		if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress()) {
		myIp = addr.getHostAddress();
		}
		}
		
		return myIp;
	}

	public DataOutputStream getOutputStream() {
		return mOutput;
	}

	public DataInputStream getInputStream() {
		return mInput;
	}

	public void writeObject(Object obj) throws IOException {
		// Serializes the object obj to a byte array, and sends the array though the socket.
		// The length of the socket is sent, so that the reciever will know how many bytes it should read.
		byte[] bytes = Serializer.serializeObject(obj);
		mOutput.writeInt(bytes.length);
		mOutput.write(bytes);
	}

	public <T> T readObject(Class<T> someClass) throws IOException {
		// Reads the length of the byte array
		int length = mInput.readInt();
		byte[] data = new byte[length];

		// Reads the bytes from the input stream
		for (int i = 0; i < length; i++)
		{
			data[i] = mInput.readByte();
		}

		// Deserializes the recieved object, using the byte array
		return Serializer.deSerializeObject(data, someClass);
	}

	public void close() throws IOException {
		// Closes the listen socket
		mServerSocket.close();
		// Closes the socket that is connected to the client
		mClientSocket.close();
		mOutput.close();
		mInput.close();
	}
}
